home *** CD-ROM | disk | FTP | other *** search
- unit Ccwsock;
-
- interface
-
- uses
- SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
- Forms, Dialogs;
- const
- { This is the base message used by Winsock to notify of Winsock asynch act }
- WM_ASYNCSELECT = WM_USER + 0;
- { These are miscellaneous constants which might be needed by an app }
- FD_SETSIZE = 64; { ??? }
- INADDR_ANY = $00000000;
- INADDR_LOOPBACK = $7F000001;
- INADDR_BROADCAST = $FFFFFFFF;
- INADDR_NONE = $FFFFFFFF;
- WSADESCRIPTION_LEN = 256; { Winsock defined vendor desc }
- WSASYS_STATUS_LEN = 128; { Winsock defined status info }
- { These are IP Protocols Standard values from Winsock ( more or less ) }
- IPPROTO_IP = 0; { dummy for IP }
- IPPROTO_ICMP = 1; { control message protocol }
- IPPROTO_GGP = 2; { gateway^2 (deprecated) }
- IPPROTO_TCP = 6; { tcp }
- IPPROTO_PUP = 12; { pup }
- IPPROTO_UDP = 17; { user datagram protocol }
- IPPROTO_IDP = 22; { xns idp }
- IPPROTO_ND = 77; { UNOFFICIAL net disk proto }
- IPPROTO_RAW = 255; { raw IP packet }
- IPPROTO_MAX = 256;
- { These are "well known" Port/socket numbers for client functions }
- IPPORT_ECHO = 7;
- IPPORT_DISCARD = 9;
- IPPORT_SYSTAT = 11;
- IPPORT_DAYTIME = 13;
- IPPORT_NETSTAT = 15;
- IPPORT_FTP = 21; { FTP Default }
- IPPORT_TELNET = 23; { Telnet Default }
- IPPORT_SMTP = 25; { SMTP Default }
- IPPORT_TIMESERVER = 37;
- IPPORT_NAMESERVER = 42;
- IPPORT_WHOIS = 43;
- IPPORT_MTP = 57;
- { These are "well known" Port/socket numbers for host specific functions }
- IPPORT_TFTP = 69;
- IPPORT_RJE = 77;
- IPPORT_FINGER = 79; { Finger Default }
- IPPORT_TTYLINK = 87;
- IPPORT_SUPDUP = 95;
- { These are "well known" UNIX TCP sockets }
- IPPORT_EXECSERVER = 512;
- IPPORT_LOGINSERVER = 513;
- IPPORT_CMDSERVER = 514;
- IPPORT_EFSSERVER = 520;
- { These are "well known" UNIX UDP sockets }
- IPPORT_BIFFUDP = 512;
- IPPORT_WHOSERVER = 513;
- IPPORT_ROUTESERVER = 520;
- { Reserved Port number base }
- IPPORT_RESERVED = 1024;
- { Link numbers (Which I don't know what are, either... :) }
- IMPLINK_IP = 155;
- IMPLINK_LOWEXPER = 156;
- IMPLINK_HIGHEXPER = 158;
- { Winsock constants }
- INVALID_SOCKET = $ffff;
- SOCKET_ERROR = (-1);
- { Socket Types; STREAM is the only one normally used }
- SOCK_STREAM = 1; { stream socket }
- SOCK_DGRAM = 2; { datagram socket }
- SOCK_RAW = 3; { raw-protocol interface }
- SOCK_RDM = 4; { reliably-delivered message }
- SOCK_SEQPACKET = 5; { sequenced packet stream }
- { Individual Socket Option flags }
- SO_DEBUG = $0001; { turn on debugging info recording }
- SO_ACCEPTCONN = $0002; { socket has had listen() }
- SO_REUSEADDR = $0004; { allow local address reuse }
- SO_KEEPALIVE = $0008; { keep connections alive }
- SO_DONTROUTE = $0010; { just use interface addresses }
- SO_BROADCAST = $0020; { permit sending of broadcast msgs }
- SO_USELOOPBACK = $0040; { bypass hardware when possible }
- SO_LINGER = $0080; { linger on close if data present }
- SO_OOBINLINE = $0100; { leave received OOB data in line }
- SO_DONTLINGER = (not SO_LINGER);
- SO_SNDBUF = $1001; { send buffer size }
- SO_RCVBUF = $1002; { receive buffer size }
- SO_SNDLOWAT = $1003; { send low-water mark }
- SO_RCVLOWAT = $1004; { receive low-water mark }
- SO_SNDTIMEO = $1005; { send timeout }
- SO_RCVTIMEO = $1006; { receive timeout }
- SO_ERROR = $1007; { get error status and clear }
- SO_TYPE = $1008; { get socket type }
- { TCP global options }
- TCP_NODELAY = $0001;
- { IP Address families }
- AF_UNSPEC = 0; { unspecified }
- AF_UNIX = 1; { local to host (pipes, portals) }
- AF_INET = 2; { internetwork: UDP, TCP, etc. }
- AF_IMPLINK = 3; { arpanet imp addresses }
- AF_PUP = 4; { pup protocols: e.g. BSP }
- AF_CHAOS = 5; { mit CHAOS protocols }
- AF_NS = 6; { XEROX NS protocols }
- AF_ISO = 7; { ISO protocols }
- AF_OSI = AF_ISO; { OSI is ISO }
- AF_ECMA = 8; { european computer manufacturers }
- AF_DATAKIT = 9; { datakit protocols }
- AF_CCITT = 10; { CCITT protocols, X.25 etc }
- AF_SNA = 11; { IBM SNA }
- AF_DECnet = 12; { DECnet }
- AF_DLI = 13; { Direct data link interface }
- AF_LAT = 14; { LAT }
- AF_HYLINK = 15; { NSC Hyperchannel }
- AF_APPLETALK = 16; { AppleTalk }
- AF_NETBIOS = 17; { NetBios-style addresses }
- AF_MAX = 18;
- { IP Protocol families, same as address families for now }
- PF_UNSPEC = AF_UNSPEC;
- PF_UNIX = AF_UNIX;
- PF_INET = AF_INET;
- PF_IMPLINK = AF_IMPLINK;
- PF_PUP = AF_PUP;
- PF_CHAOS = AF_CHAOS;
- PF_NS = AF_NS;
- PF_ISO = AF_ISO;
- PF_OSI = AF_OSI;
- PF_ECMA = AF_ECMA;
- PF_DATAKIT = AF_DATAKIT;
- PF_CCITT = AF_CCITT;
- PF_SNA = AF_SNA;
- PF_DECnet = AF_DECnet;
- PF_DLI = AF_DLI;
- PF_LAT = AF_LAT;
- PF_HYLINK = AF_HYLINK;
- PF_APPLETALK = AF_APPLETALK;
- PF_MAX = AF_MAX;
- { Level number for (get/set)sockopt() to apply to socket itself }
- SOL_SOCKET = -1; { options for socket level }
- { Maximum queue length specifiable by listen }
- SOMAXCONN = 5;
- MSG_OOB = $1; { process out-of-band data }
- MSG_PEEK = $2; { peek at incoming message }
- MSG_DONTROUTE = $4; { send without using routing tables }
- MSG_MAXIOVLEN = 16;
- { Define constant based on rfc883, used by gethostbyxxxx() calls }
- MAXGETHOSTSTRUCT = 1024;
- { Define flags to be used with the WSAAsyncSelect() call }
- FD_READ = $01;
- FD_WRITE = $02;
- FD_OOB = $04;
- FD_ACCEPT = $08;
- FD_CONNECT = $10;
- FD_CLOSE = $20;
- { All Windows Sockets error constants are biased by WSABASEERR from the norm }
- WSABASEERR = 10000;
- { Windows Sockets definitions of regular Microsoft C error constants }
- WSAEINTR = (WSABASEERR+4);
- WSAEBADF = (WSABASEERR+9);
- WSAEACCES = (WSABASEERR+13);
- WSAEFAULT = (WSABASEERR+14);
- WSAEINVAL = (WSABASEERR+22);
- WSAEMFILE = (WSABASEERR+24);
- { Windows Sockets definitions of regular Berkeley error constants }
- WSAEWOULDBLOCK = (WSABASEERR+35);
- WSAEINPROGRESS = (WSABASEERR+36);
- WSAEALREADY = (WSABASEERR+37);
- WSAENOTSOCK = (WSABASEERR+38);
- WSAEDESTADDRREQ = (WSABASEERR+39);
- WSAEMSGSIZE = (WSABASEERR+40);
- WSAEPROTOTYPE = (WSABASEERR+41);
- WSAENOPROTOOPT = (WSABASEERR+42);
- WSAEPROTONOSUPPORT = (WSABASEERR+43);
- WSAESOCKTNOSUPPORT = (WSABASEERR+44);
- WSAEOPNOTSUPP = (WSABASEERR+45);
- WSAEPFNOSUPPORT = (WSABASEERR+46);
- WSAEAFNOSUPPORT = (WSABASEERR+47);
- WSAEADDRINUSE = (WSABASEERR+48);
- WSAEADDRNOTAVAIL = (WSABASEERR+49);
- WSAENETDOWN = (WSABASEERR+50);
- WSAENETUNREACH = (WSABASEERR+51);
- WSAENETRESET = (WSABASEERR+52);
- WSAECONNABORTED = (WSABASEERR+53);
- WSAECONNRESET = (WSABASEERR+54);
- WSAENOBUFS = (WSABASEERR+55);
- WSAEISCONN = (WSABASEERR+56);
- WSAENOTCONN = (WSABASEERR+57);
- WSAESHUTDOWN = (WSABASEERR+58);
- WSAETOOMANYREFS = (WSABASEERR+59);
- WSAETIMEDOUT = (WSABASEERR+60);
- WSAECONNREFUSED = (WSABASEERR+61);
- WSAELOOP = (WSABASEERR+62);
- WSAENAMETOOLONG = (WSABASEERR+63);
- WSAEHOSTDOWN = (WSABASEERR+64);
- WSAEHOSTUNREACH = (WSABASEERR+65);
- WSAENOTEMPTY = (WSABASEERR+66);
- WSAEPROCLIM = (WSABASEERR+67);
- WSAEUSERS = (WSABASEERR+68);
- WSAEDQUOT = (WSABASEERR+69);
- WSAESTALE = (WSABASEERR+70);
- WSAEREMOTE = (WSABASEERR+71);
- { Extended Windows Sockets error constant definitions }
- WSASYSNOTREADY = (WSABASEERR+91);
- WSAVERNOTSUPPORTED = (WSABASEERR+92);
- WSANOTINITIALISED = (WSABASEERR+93);
- { Authoritative Answer: Host not found }
- WSAHOST_NOT_FOUND = (WSABASEERR+1001);
- HOST_NOT_FOUND = WSAHOST_NOT_FOUND;
- { Non-Authoritative: Host not found, or SERVERFAIL }
- WSATRY_AGAIN = (WSABASEERR+1002);
- TRY_AGAIN = WSATRY_AGAIN;
- { Non recoverable errors, FORMERR, REFUSED, NOTIMP }
- WSANO_RECOVERY = (WSABASEERR+1003);
- NO_RECOVERY = WSANO_RECOVERY;
- { Valid name, no data record of requested type }
- WSANO_DATA = (WSABASEERR+1004);
- NO_DATA = WSANO_DATA;
- { no address, look for MX record }
- WSANO_ADDRESS = WSANO_DATA;
- NO_ADDRESS = WSANO_ADDRESS;
- { Windows Sockets errors redefined as regular Berkeley error constants }
- EWOULDBLOCK = WSAEWOULDBLOCK;
- EINPROGRESS = WSAEINPROGRESS;
- EALREADY = WSAEALREADY;
- ENOTSOCK = WSAENOTSOCK;
- EDESTADDRREQ = WSAEDESTADDRREQ;
- EMSGSIZE = WSAEMSGSIZE;
- EPROTOTYPE = WSAEPROTOTYPE;
- ENOPROTOOPT = WSAENOPROTOOPT;
- EPROTONOSUPPORT = WSAEPROTONOSUPPORT;
- ESOCKTNOSUPPORT = WSAESOCKTNOSUPPORT;
- EOPNOTSUPP = WSAEOPNOTSUPP;
- EPFNOSUPPORT = WSAEPFNOSUPPORT;
- EAFNOSUPPORT = WSAEAFNOSUPPORT;
- EADDRINUSE = WSAEADDRINUSE;
- EADDRNOTAVAIL = WSAEADDRNOTAVAIL;
- ENETDOWN = WSAENETDOWN;
- ENETUNREACH = WSAENETUNREACH;
- ENETRESET = WSAENETRESET;
- ECONNABORTED = WSAECONNABORTED;
- ECONNRESET = WSAECONNRESET;
- ENOBUFS = WSAENOBUFS;
- EISCONN = WSAEISCONN;
- ENOTCONN = WSAENOTCONN;
- ESHUTDOWN = WSAESHUTDOWN;
- ETOOMANYREFS = WSAETOOMANYREFS;
- ETIMEDOUT = WSAETIMEDOUT;
- ECONNREFUSED = WSAECONNREFUSED;
- ELOOP = WSAELOOP;
- ENAMETOOLONG = WSAENAMETOOLONG;
- EHOSTDOWN = WSAEHOSTDOWN;
- EHOSTUNREACH = WSAEHOSTUNREACH;
- ENOTEMPTY = WSAENOTEMPTY;
- EPROCLIM = WSAEPROCLIM;
- EUSERS = WSAEUSERS;
- EDQUOT = WSAEDQUOT;
- ESTALE = WSAESTALE;
- EREMOTE = WSAEREMOTE;
- IOCPARM_MASK = $7f;
- IOC_VOID = $20000000;
- IOC_OUT = $40000000;
- IOC_IN = $80000000;
- IOC_INOUT = (IOC_IN or IOC_OUT);
-
- FIONREAD = IOC_OUT or { get # bytes to read }
- ((Longint(SizeOf(Longint)) and IOCPARM_MASK) shl 16) or
- (Longint(Byte('f')) shl 8) or 127;
- FIONBIO = IOC_IN or { set/clear non-blocking i/o }
- ((Longint(SizeOf(Longint)) and IOCPARM_MASK) shl 16) or
- (Longint(Byte('f')) shl 8) or 126;
- FIOASYNC = IOC_IN or { set/clear async i/o }
- ((Longint(SizeOf(Longint)) and IOCPARM_MASK) shl 16) or
- (Longint(Byte('f')) shl 8) or 125;
-
- type
- u_char = Char;
- u_short = Word;
- u_int = Cardinal;
- u_long = Longint;
-
- { These are type definitions to ease using a C DLL }
- Unsigned_Character = byte;
- Unsigned_Short_Integer = u_short;
- Unsigned_Integer = Cardinal;
- Unsigned_Long_Integer = u_long;
- { We have to do this because a Socket in Winsock is a U_INT }
- TSocket = Unsigned_Integer;
- { Another C structure from Winsock; originally called "servent"** conv ** }
- Server_Entry = packed record
- Server_Name : PChar;
- Server_Aliases : ^PChar; { Note double indirection here; array of PChar }
- Server_Port : SmallInt;
- Server_Protocol : PChar;
- end;
- PServer_Entry = ^Server_Entry;
- { This C structure was originally called "protoent" *** converted *** }
- Protocol_Entry = packed record
- Protocol_Name : PChar;
- Protocol_Aliases : ^PChar; { Another array of PChar }
- Protocol_Id : SmallInt;
- end;
- PProtocol_Entry = ^Protocol_Entry;
- { This is a clever variant record useful for casting internet addresses }
- { originally called TInAddr *** converted *** }
- Internet_Address = packed record
- Case Integer of
- 0: ( Net_Byte ,
- Host_Byte ,
- Local_Host_Byte ,
- Local_Machine_Byte : Unsigned_Character );
- 1: ( Network_Portion ,
- Local_Machine_Portion : Unsigned_Short_Integer );
- 2: ( Full_Internet_Address : Unsigned_Long_Integer );
- end;
- PInternet_address = ^Internet_Address;
- { This structure was originally known as "sockaddr_in" **converted**}
- Internet_Socket_Address = packed record
- case Integer of
- 0 : (Socket_Family : u_short;
- Socket_Port : Unsigned_Short_Integer;
- Socket_Address : Internet_Address;
- Socket_Padding_Array : array[ 0 .. 7 ] of char );
- 1 : (A_Socket_family : u_short;
- Socket_Data : array[ 0 .. 13 ] of Char )
- end;
- PInternet_Socket_Address = ^Internet_Socket_Address;
- { This structure's C name is "hostent" **** converted ****}
- Host_Entry = packed record
- Host_Name : PChar;
- Host_Aliases : ^PChar;
- Host_Address_Type : smallint;
- Host_Address_Length : smallint;
- Case Integer of { Another useful variant record }
- 0: ( host_address_list : ^PChar ); { Double pointer again }
- 1: ( host_address : ^PInternet_address );
- end;
- PHost_entry = ^Host_Entry;
- { This is usually called WSADATA **converted**}
- Winsock_Implementation_Data = packed record
- Winsock_Version : word;
- Winsock_High_Version : word;
- { Note these two arrays are based on global constants for size }
- Description_String : array[ 0 .. WSADESCRIPTION_LEN ] of char;
- System_Status_String : array[ 0 .. WSASYS_STATUS_LEN ] of char;
- Maximum_Sockets_Allowed : Unsigned_Short_Integer;
- Maximum_UDP_Datagram_Size : Unsigned_Short_Integer;
- Vendor_Specific_String : PChar;
- end;
- { This is usually known as "sockaddr" **converted**}
- Generic_Socket_Address = Internet_Socket_Address;
- { This in C is "sockproto" }
- Socket_Protocol = packed record
- Protocol_Family : Unsigned_Short_Integer;
- Protocol_Id : Unsigned_Short_Integer;
- end;
- { This is sometimes called the "linger" structure; used only at shutdown }
- Lingering_Control = packed record
- Linger_Status : Unsigned_Short_Integer;
- Linger_Interval : Unsigned_Short_Integer;
- end;
- { These two event data types are used to hook into the Winsock Asynch system }
- TWSAEvent = procedure( Sender : TObject; Socket : TSocket ) of object;
- TWSAError = procedure( Sender : TObject;
- ErrorCode : Integer;
- TheMessage : String ) of object;
- { This is an OOP wrapper around the Winsock calls; tries to buffer a bit }
- TCCSocket = class( TWinControl )
- public
- Socket_WSA_Data : Winsock_Implementation_Data;
- ErrorCode : Integer;
- FullErrorMessage : string;
- WinsockErrorMessage : string;
- Socket_Server_Entry : PServer_Entry;
- Socket_Host_Entry : Phost_entry;
- Socket_Protocol_Entry : PProtocol_Entry;
- Socket_IP_Address : Internet_Socket_Address;
- FPort_Name : String;
- FIP_Address_Name : String;
- FSocket : TSocket;
- FMasterSocket : TSocket;
- FBlockingMode : Boolean;
- FTimeoutValue : Integer;
- FOnDataIsAvailable : TWSAEvent;
- FOnDataCanBeSent : TWSAEvent;
- FOnOOBDataIsAvailable : TWSAEvent;
- FOnSessionClosed : TWSAEvent;
- FOnSessionIsAvailable : TWSAEvent;
- FOnSessionConnected : TWSAEvent;
- FOnErrorOccurred : TWSAError;
- procedure SetStringData( TheData: string );
- function GetStringData : string;
- procedure SetStringDataOutOfBand( TheData: string );
- function GetStringDataOutOfBand : string;
- function PeekCurrentData : string;
- function GetSocketErrorDescription( ErrorCode : Integer) : string;
- procedure SetSocketErrorData( SocketFunction : string );
- procedure TWMPaint( var Msg : TWMPaint ); message WM_PAINT;
- procedure ActivateNonAsynchTimeout;
- procedure DeactivateNonAsynchTimeout;
- procedure WMASyncSelect( var Msg : TMessage ); message WM_ASYNCSELECT;
- procedure WMTimer( var Msg : TMessage ); message WM_TIMER;
- constructor Create( AOwner : TComponent ); override;
- destructor Destroy; override;
- procedure CCSockConnect;
- procedure CCSockClose;
- procedure CCSockListen;
- procedure CCSockCancelListen;
- function CCSockReceive( TheSocket : TSocket;
- TheTextBuffer : PChar;
- var TheTextLength : Integer
- ) : Integer;
- function CCSockSend( TheSocket : TSocket;
- TheTextBuffer : PChar;
- var TheTextLength : Integer
- ) : Integer;
- function CCSockAccept : TSocket;
- function GetSocketIPAddress( TheSocket: TSocket ) : string;
- function GetSocketPort( TheSocket : TSocket ) : string;
- function GetSocketPeerIPAddress( TheSocket : TSocket ) : string;
- function GetSocketPeerPort( TheSocket : TSocket ) : string;
- function SocketIsNotBlocking : Boolean;
- procedure ActivateBlockingMode( BeginBlocking : Boolean );
- property StringData : string
- read GetStringData write SetStringData;
- property PeekData : string
- read PeekCurrentData;
- property OutOfBand : string
- read GetStringDataOutOfBand write SetStringDataOutOfBand;
- property TheSocket : TSocket
- read FSocket write FSocket;
- property TheMasterSocket : TSocket
- read FMasterSocket write FMasterSocket;
- published
- property IPAddressName : string
- read FIP_Address_Name write FIP_Address_Name;
- property PortName : string
- read FPort_Name write FPort_Name;
- property AsynchMode : Boolean
- read SocketIsNotBlocking write ActivateBlockingMode default True;
- property NonAsynchTimeoutValue : Integer
- read FTimeoutValue write FTimeoutValue default 30;
- property OnDataIsAvailable : TWSAEvent
- read FOnDataIsAvailable write FOnDataIsAvailable;
- property OnOOBDataIsAvailable : TWSAEvent
- read FOnOOBDataIsAvailable write FOnOOBDataIsAvailable;
- property OnDataCanBeSent : TWSAEvent
- read FOnDataCanBeSent write FOnDataCanBeSent;
- property OnSessionClosed : TWSAEvent
- read FOnSessionClosed write FOnSessionClosed;
- property OnSessionIsAvailable : TWSAEvent
- read FOnSessionIsAvailable write FOnSessionIsAvailable;
- property OnSessionConnected : TWSAEvent
- read FOnSessionConnected write FOnSessionConnected;
- property OnErrorOccurred : TWSAError
- read FOnErrorOccurred write FOnErrorOccurred;
- end;
- { External calls to Winsock DLL functions; names are kept the same }
- { to ease documentation lookup }
- function accept( TheSocket : TSocket;
- var TheAddress : Internet_Socket_Address;
- var TheAddressLength : Integer
- ) : TSocket; stdcall;
- function bind( TheSocket : TSocket;
- var TheAddress : Internet_Socket_Address;
- TheNameLength : Integer
- ) : Integer; stdcall;
- function closesocket( TheSocket : TSocket ) : Integer; stdcall;
- function connect( TheSocket : TSocket;
- var TheName : Internet_Socket_Address;
- TheNameLength : Integer
- ) : Integer; stdcall;
- function ioctlsocket( TheSocket : TSocket;
- TheCommand : longint;
- var TheCommandParameter : u_long
- ) : Integer; stdcall;
- function getpeername( TheSocket : TSocket;
- var TheName : Internet_Socket_Address;
- var TheNameLength : Integer
- ) : Integer; stdcall;
- function getsockname( TheSocket : TSocket;
- var TheName : Internet_Socket_Address;
- var TheNameLength : Integer
- ) : Integer; stdcall;
- function getsockopt( TheSocket : TSocket;
- TheStackLevel : Integer;
- TheOptionName : Integer;
- TheOptionStatus : PChar;
- var TheOptionStatusLength : Integer
- ) : Integer; stdcall;
- function htonl( HostOrderLongInt : Unsigned_Long_Integer ) :
- Unsigned_Long_Integer; stdcall;
- function htons( HostOrderShortInt : Unsigned_Short_Integer ) :
- Unsigned_Short_Integer; stdcall;
- function inet_addr( IPAddressName : PChar ) :
- Unsigned_Long_Integer; stdcall;
- function inet_ntoa( Socket_IP_Address: Internet_Address ) :
- PChar; stdcall;
- function listen( TheSocket : TSocket; Backlog : Integer ) :
- Integer; stdcall;
- function ntohl( NetOrderLongInt : Unsigned_Long_Integer ) :
- Unsigned_Long_Integer; stdcall;
- function ntohs( NetOrderShortInt : Unsigned_Short_Integer ) :
- Unsigned_Short_Integer; stdcall;
- function recv( TheSocket : TSocket;
- TheDataBuffer : PChar;
- TheDataLength : Integer;
- TheFlags : Integer
- ) : Integer; stdcall;
- function recvfrom( TheSocket : TSocket;
- TheDataBuffer : PChar;
- TheDataLength : Integer;
- TheFlags : Integer;
- var SocketToReceiveFrom : Internet_Socket_Address;
- var SocketToReceiveFromLength : Integer
- ) : Integer; stdcall;
- function send( TheSocket : TSocket;
- TheDataBuffer : PChar;
- TheDataLength : Integer;
- TheFlags : Integer
- ) : Integer; stdcall;
- function sendto( TheSocket : TSocket;
- TheDataBuffer : PChar;
- TheDataLength : Integer;
- TheFlags : Integer;
- var SocketToSendTo : Internet_Socket_Address;
- SocketToSendToLength : Integer
- ) : Integer; stdcall;
- function setsockopt( TheSocket : TSocket;
- TheStackLevel : Integer;
- TheOptionName : Integer;
- TheOptionStatus : PChar;
- TheOptionStatusLength : Integer
- ) : Integer; stdcall;
- function shutdown( TheSocket : TSocket;
- ActionToShutDown : Integer
- ) : Integer; stdcall;
- function socket( AddressFamily : Integer;
- SocketType : Integer;
- ProtocolCode : Integer
- ) : TSocket; stdcall;
- function gethostbyaddr( TheAddress : Pointer;
- TheDataLength : Integer;
- SocketType : Integer
- ) : PHost_Entry; stdcall;
- function gethostbyname( TheName : PChar ) :
- PHost_Entry; stdcall;
- function gethostname( TheName : PChar; TheLength : Integer ) : Integer; stdcall;
- function getservbyport( PortCode : Integer;
- ProtocolName : PChar
- ) : PServer_Entry; stdcall;
- function getservbyname( TheName : PChar;
- ProtocolName : PChar
- ) : PServer_Entry; stdcall;
- function getprotobynumber( ProtocolCode : Integer ) :
- PProtocol_Entry; stdcall;
- function getprotobyname( TheName : PChar ) :
- PProtocol_Entry; stdcall;
- { Winsock Asynchronous Message-based Extensions to Berkeley Sockets }
- function WSAStartup( wVersionRequired : word;
- var WIDRecord : Winsock_Implementation_Data
- ) : Integer; stdcall;
- function WSACleanup : Integer; stdcall;
- procedure WSASetLastError( ErrorCode : Integer ); stdcall;
- function WSAGetLastError : Integer; stdcall;
- function WSAIsBlocking : Boolean; stdcall;
- function WSAUnhookBlockingHook: Integer; stdcall;
- function WSASetBlockingHook( TheBlockingFunction : TFarProc ) : TFarProc; stdcall;
- function WSACancelBlockingCall : Integer; stdcall;
- function WSAAsyncGetServByName( Handle : HWND;
- Msg : Unsigned_Integer;
- TheName : PChar;
- ProtocolName : PChar;
- TheDataBuffer : PChar;
- TheBufferLength : Integer
- ) : THandle; stdcall;
- function WSAAsyncGetServByPort( Handle : HWND;
- Msg : Unsigned_Integer;
- PortCode : SmallInt;
- ProtocolName : PChar;
- TheDataBuffer : PChar;
- TheBufferLength : Integer
- ) : THandle; stdcall;
- function WSAAsyncGetProtoByName( Handle : HWND;
- Msg : Unsigned_Integer;
- TheName : PChar;
- TheDataBuffer : PChar;
- TheBufferLength : Integer
- ) : THandle; stdcall;
- function WSAAsyncGetProtoByNumber( Handle : HWND;
- Msg : Unsigned_Integer;
- HBOProtocolNumber : Integer;
- TheDataBuffer : PChar;
- TheBufferLength : Integer
- ) : THandle; stdcall;
- function WSAAsyncGetHostByName( Handle : HWND;
- Msg : Unsigned_Integer;
- TheName : PChar;
- TheDataBuffer : PChar;
- TheBufferLength : Integer
- ) : THandle; stdcall;
- function WSAAsyncGetHostByAddr( Handle : HWND;
- Msg : Unsigned_Integer;
- TheAddress : PChar;
- TheDataLength : Integer;
- AddressType : Integer;
- TheDataBuffer : PChar;
- TheBufferLength : Integer
- ) : THandle; stdcall;
- function WSACancelAsyncRequest( Handle : THandle) :
- Integer; stdcall;
- function WSAAsyncSelect( TheSocket : TSocket;
- Handle : HWND;
- Msg : Unsigned_Integer;
- AsynchEventCode : Integer
- ) : Integer; stdcall;
-
-
- implementation
-
- const
- winsocket = 'wsock32.dll';
-
- function accept; external winsocket name 'accept';
- function bind; external winsocket name 'bind';
- function closesocket; external winsocket name 'closesocket';
- function connect; external winsocket name 'connect';
- function getpeername; external winsocket name 'getpeername';
- function getsockname; external winsocket name 'getsockname';
- function getsockopt; external winsocket name 'getsockopt';
- function htonl; external winsocket name 'htonl';
- function htons; external winsocket name 'htons';
- function inet_addr; external winsocket name 'inet_addr';
- function inet_ntoa; external winsocket name 'inet_ntoa';
- function ioctlsocket; external winsocket name 'ioctlsocket';
- function listen; external winsocket name 'listen';
- function ntohl; external winsocket name 'ntohl';
- function ntohs; external winsocket name 'ntohs';
- function recv; external winsocket name 'recv';
- function recvfrom; external winsocket name 'recvfrom';
- function send; external winsocket name 'send';
- function sendto; external winsocket name 'sendto';
- function setsockopt; external winsocket name 'setsockopt';
- function shutdown; external winsocket name 'shutdown';
- function socket; external winsocket name 'socket';
- function gethostbyaddr; external winsocket name 'gethostbyaddr';
- function gethostbyname; external winsocket name 'gethostbyname';
- function getprotobyname; external winsocket name 'getprotobyname';
- function getprotobynumber; external winsocket name 'getprotobynumber';
- function getservbyname; external winsocket name 'getservbyname';
- function getservbyport; external winsocket name 'getservbyport';
- function gethostname; external winsocket name 'gethostname';
- function WSAAsyncSelect; external winsocket name 'WSAAsyncSelect';
- function WSAAsyncGetHostByAddr; external winsocket name 'WSAAsyncGetHostByAddr';
- function WSAAsyncGetHostByName; external winsocket name 'WSAAsyncGetHostByName';
- function WSAAsyncGetProtoByNumber; external winsocket name 'WSAAsyncGetProtoByNumber';
- function WSAAsyncGetprotoByName; external winsocket name 'WSAAsyncGetprotoByName';
- function WSAAsyncGetServByPort; external winsocket name 'WSAAsyncGetServByPort';
- function WSAAsyncGetServByName; external winsocket name 'WSAAsyncGetServByName';
- function WSACancelAsyncRequest; external winsocket name 'WSACancelAsyncRequest';
- function WSASetBlockingHook; external winsocket name 'WSASetBlockingHook';
- function WSAUnhookBlockingHook; external winsocket name 'WSAUnhookBlockingHook';
- function WSAGetLastError; external winsocket name 'WSAGetLastError';
- procedure WSASetLastError; external winsocket name 'WSASetLastError';
- function WSACancelBlockingCall; external winsocket name 'WSACancelBlockingCall';
- function WSAIsBlocking; external winsocket name 'WSAIsBlocking';
- function WSAStartup; external winsocket name 'WSAStartup';
- function WSACleanup; external winsocket name 'WSACleanup';
-
- { This is the override create method for the socket component }
- constructor TCCSocket.Create( AOwner : TComponent );
- var
- ReturnCode : Integer; { Used to signal error }
- begin
- { Call inherited first! }
- inherited Create( AOwner );
- { Enable Asynch mode since in Windows }
- FBlockingMode := false;
- { Set Timeout for asynch ops }
- FTimeoutValue := 30;
- { Set up no sockets in the two native vars }
- FSocket := INVALID_SOCKET;
- FMasterSocket := INVALID_SOCKET;
- { Start up Winsock }
- ReturnCode := WSAStartup( $101 , Socket_WSA_Data );
- { If don't get 0 store the error code }
- if ReturnCode <> 0 then SetSocketErrorData( 'Constructor (WSAStartup)' );
- end;
-
- { This is the destroy override method }
- destructor TCCSocket.Destroy;
- var
- ReturnCode : Integer; { Holds possible error code }
- begin
- { Attempt to shut down winsock }
- ReturnCode := WSACleanup;
- { If didn't get 0 save the error }
- if ReturnCode < 0 then SetSocketErrorData( 'Destructor (WSACleanup)' );
- { call inherited }
- inherited Destroy;
- end;
-
- { This is just used to draw the nonvisual element during design time }
- procedure TCCSocket.TWMPaint( var Msg : TWMPaint );
- var
- TheIcon : HIcon; { Internal icon }
- TheDC : HDC; { Internal dc }
- begin
- { If in design mode draw the icon }
- if csDesigning in ComponentState then
- begin
- { Load the icon from the instance via the DCR file }
- TheIcon := LoadIcon( HInstance , MAKEINTRESOURCE( 'TCCSocket' ));
- { Get a device context }
- TheDC := GetDC( Handle );
- { Set the internal width to that of an icon }
- Width := 32;
- Height := 32;
- { Display the icon }
- DrawIcon( TheDC , 0 , 0 , TheIcon );
- { Get rid of the evidence }
- ReleaseDC( Handle , TheDC );
- FreeResource( TheIcon );
- end;
- { Let Windows know drawing is done }
- ValidateRect( Handle , nil );
- end;
-
- { Function to return Asynch mode }
- function TCCSocket.SocketIsNotBlocking: Boolean;
- begin
- { return inverse of blocking mode }
- SocketIsNotBlocking := not FBlockingMode;
- end;
-
- { This turns off asynch mode via inverse of parameter }
- procedure TCCSocket.ActivateBlockingMode( BeginBlocking: Boolean );
- begin
- FBlockingMode := not BeginBlocking;
- end;
-
- { This is a full access method to send a string over the socket }
- procedure TCCSocket.SetStringData( TheData : string );
- var
- BytesLeftToSend , { Counter for remaining data }
- BytesSentSoFar : Integer; { Counter for sent data }
- DataBuffer : array[0..256] of char; { Buffer for string }
- DataBufferPointer : PChar; { Pointer to buffer }
- begin
- { Copy string into char array }
- StrPCopy( DataBuffer , TheData );
- { Move the pointer to the array's first element into the PChar }
- DataBufferPointer := @DataBuffer[ 0 ];
- { Count the total chars to send }
- BytesLeftToSend := Length( TheData );
- { Run a loop to send the string over the socket }
- while BytesLeftToSend > 0 do
- begin
- { Start a timeout timer if not in blocking mode }
- if not FBlockingMode then ActivateNonAsynchTimeout;
- { Send some bytes over the net }
- BytesSentSoFar := send( FSocket , DataBufferPointer , BytesLeftToSend , 0 );
- { End timeout timer if not blocking }
- if not FBlockingMode then DeactivateNonAsynchTimeout;
- { If get a negative response code then signal error }
- if BytesSentSoFar < 0 then
- begin
- { Save the error data }
- SetSocketErrorData( 'SetStringData (Send)' );
- end
- else
- begin
- { Decrement total bytes left to send }
- BytesLeftToSend := BytesLeftToSend - BytesSentSoFar;
- { Increment pointer into the string }
- DataBufferPointer := DataBufferPointer + BytesSentSoFar;
- end;
- end;
- end;
-
- { This is a full access method to read a string from the socket }
- function TCCSocket.GetStringData: string;
- var
- TheDataLength : Integer; { Length of data received }
- DataBuffer : string; { String to store data in }
- DataBufferArray : array[ 0 .. 256 ] of char absolute DataBuffer;
- { Map Pointer to string on stack }
- begin
- { If the socket has been set up try to get some data }
- if FSocket <> INVALID_SOCKET then
- begin
- { Activate timeout timer if not in blocking mode }
- if not FBlockingMode then ActivateNonAsynchTimeout;
- { Do a receive on any data waiting at the socket }
- TheDataLength := recv( FSocket , @DataBufferArray[ 1 ] , 255 , 0 );
- { If not blocking kill timeout timer }
- if not FBlockingMode then DeactivateNonAsynchTimeout;
- { If negative data length then set error }
- if TheDataLength < 0 then
- begin
- { Set the socket error conditions }
- SetSocketErrorData( 'GetStringData (Recv)' );
- { Return nothing }
- Result := '';
- end
- else
- begin
- { Set up pascal style string }
- DataBufferArray[ 0 ] := Chr( TheDataLength );
- { And return the prepared string as result }
- Result := DataBuffer;
- end;
- end
- else Result := ''; { Return empty string if invalid socket }
- end;
-
- { This is a full access method to send a string as OOB data }
- procedure TCCSocket.SetStringDataOutOfBand( TheData: string );
- var
- BytesLeftToSend , { Counter for remaining data }
- BytesSentSoFar : Integer; { Counter for sent data }
- DataBuffer : array[0..256] of char; { Buffer for string }
- DataBufferPointer : PChar; { Pointer to buffer }
- begin
- { Copy string into char array }
- StrPCopy( DataBuffer , TheData );
- { Move the pointer to the array's first element into the PChar }
- DataBufferPointer := @DataBuffer[ 0 ];
- { Count the total chars to send }
- BytesLeftToSend := Length( TheData );
- { Run a loop to send the string over the socket }
- while BytesLeftToSend > 0 do
- begin
- { Start a timeout timer if not in blocking mode }
- if not FBlockingMode then ActivateNonAsynchTimeout;
- { Send some bytes over the net }
- BytesSentSoFar := send( FSocket , DataBufferPointer ,
- BytesLeftToSend , MSG_OOB );
- { End timeout timer if not blocking }
- if not FBlockingMode then DeactivateNonAsynchTimeout;
- { If get a negative response code then signal error }
- if BytesSentSoFar < 0 then
- begin
- { Save the error data }
- SetSocketErrorData( 'SetStringDataOutOfBand (Send)' );
- end
- else
- begin
- { Decrement total bytes left to send }
- BytesLeftToSend := BytesLeftToSend - BytesSentSoFar;
- { Increment pointer into the string }
- DataBufferPointer := DataBufferPointer + BytesSentSoFar;
- end;
- end;
- end;
-
- { This is a full access method to receive out of band data as a string }
- function TCCSocket.GetStringDataOutOfBand: string;
- var
- TheDataLength : Integer; { Length of data received }
- DataBuffer : string; { String to store data in }
- DataBufferArray : array[ 0 .. 256 ] of char absolute DataBuffer;
- { Map Pointer to string on stack }
- begin
- { If the socket has been set up try to get some data }
- if FSocket <> INVALID_SOCKET then
- begin
- { Activate timeout timer if not in blocking mode }
- if not FBlockingMode then ActivateNonAsynchTimeout;
- { Do a receive on any data waiting at the socket }
- TheDataLength := recv( FSocket , @DataBufferArray[ 1 ] , 255 , MSG_OOB );
- { If not blocking kill timeout timer }
- if not FBlockingMode then DeactivateNonAsynchTimeout;
- { If negative data length then set error }
- if TheDataLength < 0 then
- begin
- { Set the socket error conditions }
- SetSocketErrorData( 'GetStringDataOutOfBand (Recv)' );
- { Return nothing }
- Result := '';
- end
- else
- begin
- { Set up pascal style string }
- DataBufferArray[ 0 ] := Chr( TheDataLength );
- { And return the prepared string as result }
- Result := DataBuffer;
- end;
- end
- else Result := ''; { Return empty string if invalid socket }
- end;
-
- function TCCSocket.PeekCurrentData: string;
- var
- TheDataLength : Integer; { Length of data received }
- DataBuffer : string; { String to store data in }
- DataBufferArray : array[ 0 .. 256 ] of char absolute DataBuffer;
- { Map Pointer to string on stack }
- begin
- { If the socket has been set up try to get some data }
- if FSocket <> INVALID_SOCKET then
- begin
- { Activate timeout timer if not in blocking mode }
- if not FBlockingMode then ActivateNonAsynchTimeout;
- { Do a receive on any data waiting at the socket }
- TheDataLength := recv( FSocket , @DataBufferArray[ 1 ] , 255 , MSG_PEEK );
- { If not blocking kill timeout timer }
- if not FBlockingMode then DeactivateNonAsynchTimeout;
- { If negative data length then set error }
- if TheDataLength < 0 then
- begin
- { Set the socket error conditions }
- SetSocketErrorData( 'PeekCurrentData (PeekData)' );
- { Return nothing }
- Result := '';
- end
- else
- begin
- { Set up pascal style string }
- DataBufferArray[ 0 ] := Chr( TheDataLength );
- { And return the prepared string as result }
- Result := DataBuffer;
- end;
- end
- else Result := ''; { Return empty string if invalid socket }
- end;
-
- { This is a full access method to get the port id for a given socket }
- function TCCSocket.GetSocketPort( TheSocket : TSocket ) : string;
- var
- TheAddress : Internet_Socket_Address; { Hold address info }
- TheAddressLength : Integer; { Hold addr info length }
- begin
- { Find out the size of the structure }
- TheAddressLength := SizeOf( TheAddress );
- { Call the winsock dll routine }
- getsockname( TheSocket , TheAddress , TheAddressLength );
- { Pull off the properly-byte-ordered port number as a string }
- Result := IntToStr( ntohs( TheAddress.Socket_Port ));
- end;
-
- { This is a full access method to get the IP Address of a given socket }
- function TCCSocket.GetSocketIPAddress( TheSocket : TSocket ) : string;
- var
- TheAddress : Internet_Socket_Address; { Holds address info }
- TheAddressLength : Integer; { Holds size of info }
- AddressPChar : PChar; { holds converted info }
- begin
- { Get the size of the address record }
- TheAddressLength := SizeOf( TheAddress );
- { Call the Winsock DLL function }
- getsockname( TheSocket , TheAddress , TheAddressLength );
- { Make the conversion from 32 bit to dotted decimal }
- AddressPChar := inet_ntoa( TheAddress.Socket_Address );
- { return it as a pascal string }
- Result := StrPas( AddressPChar );
- end;
-
- { This is a full access method to get the port number of the other end of a socket }
- function TCCSocket.GetSocketPeerPort( TheSocket : TSocket ) : string;
- var
- TheAddress : Internet_Socket_Address; { Hold address info }
- TheAddressLength : Integer; { Hold addr info length }
- begin
- { Find out the size of the structure }
- TheAddressLength := SizeOf( TheAddress );
- { Call the winsock dll routine }
- getpeername( TheSocket , TheAddress , TheAddressLength );
- { Pull off the properly-byte-ordered port number as a string }
- Result := IntToStr( ntohs( TheAddress.Socket_Port ));
- end;
-
- { This is a full access method to get the ip address of the other end of a socket }
- function TCCSocket.GetSocketPeerIPAddress(TheSocket: TSocket): string;
- var
- TheAddress : Internet_Socket_Address; { Holds address info }
- TheAddressLength : Integer; { Holds size of info }
- AddressPChar : PChar; { holds converted info }
- begin
- { Get the size of the address record }
- TheAddressLength := SizeOf( TheAddress );
- { Call the Winsock DLL function }
- getpeername( TheSocket , TheAddress , TheAddressLength );
- { Make the conversion from 32 bit to dotted decimal }
- AddressPChar := inet_ntoa( TheAddress.Socket_Address );
- { return it as a pascal string }
- Result := StrPas( AddressPChar );
- end;
-
- { This is a full access method to receive a PChar of up to 64K of data at once }
- function TCCSocket.CCSockReceive( TheSocket : TSocket;
- TheTextBuffer : PChar;
- var TheTextLength : Integer
- ) : Integer;
- begin
- { If not an invalid socket then do the receive }
- if FSocket <> INVALID_SOCKET then
- begin
- { If not in block mode then activate timeout timer }
- if not FBlockingMode then ActivateNonAsynchTimeout;
- { Return the direct result of the recv call into Winsock }
- Result := recv( TheSocket , TheTextBuffer , TheTextLength , 0 );
- { If not blocking kill timeout timer }
- if not FBlockingMode then DeactivateNonAsynchTimeout;
- { If negative length then get error info }
- if TheTextLength < 0 then SetSocketErrorData( 'CCSockReceive' );
- end
- else Result := -1; { Return invalid PChar if not valid socket }
- end;
-
- { This is a full access method to send a PChar of up to 64K of data at once }
- function TCCSocket.CCSockSend( TheSocket : TSocket;
- TheTextBuffer : PChar;
- var TheTextLength : Integer
- ) : Integer;
- begin
- { If not blocking then activate timeout timer }
- if not FBlockingMode then ActivateNonAsynchTimeout;
- { Send the info through raw }
- TheTextLength := send( TheSocket , TheTextBuffer , TheTextLength , 0 );
- { if not blocking then deactivate timeout timer }
- if not FBlockingMode then DeactivateNonAsynchTimeout;
- { if error code then get winsock error status }
- if TheTextLength < 0 then SetSocketErrorData( 'CCSockSend' );
- { return SOCKET_ERROR or number of bytes sent }
- Result := TheTextLength;
- end;
-
- { This method handles Asynchronous Windows messages for the Winsock }
- procedure TCCSocket.WMASyncSelect( var Msg : TMessage );
- begin
- { The low word of the lParam field of the Msg is the event code }
- case LoWord( Msg.lParam ) of
- { This indicates data is available for reading on the socket }
- FD_READ : begin
- if Assigned( FOnDataIsAvailable ) then
- FOnDataIsAvailable( Self , Msg.wParam ); { wParam = socket ID }
- end;
- { This indicates data is available for sending on the socket }
- FD_WRITE : begin
- if Assigned( FOnDataCanBeSent ) then
- FOnDataCanBeSent( Self , Msg.wParam );
- end;
- { This indicates OOB data is available for reading on the socket }
- FD_OOB : begin
- if Assigned( FOnOOBDataIsAvailable ) then
- FOnOOBDataIsAvailable( Self , Msg.wParam );
- end;
- { This indicates the socket has an incoming connection for accept }
- FD_ACCEPT : begin
- if Assigned( FOnSessionIsAvailable ) then
- FOnSessionIsAvailable( Self , Msg.wParam );
- end;
- { This indicates an outgoing connection has been accepted by peer }
- FD_CONNECT: begin
- if Assigned( FOnSessionConnected ) then
- FOnSessionConnected( Self , Msg.wParam );
- end;
- { This indicates the socket has been closed; presumably by peer }
- FD_CLOSE : begin
- if Assigned( FOnSessionClosed ) then
- FOnSessionClosed( Self , Msg.wParam );
- end;
- end;
- end;
-
- { This handles Asynchronous Timeouts gracefully }
- procedure TCCSocket.WMTimer( var Msg : TMessage );
- begin
- { Kill a running timer }
- KillTimer( Handle , 10 );
- { If the socket is blocking then deal with timeout }
- if WSAIsBlocking then
- begin
- { Cancel the blocking operation }
- WSACancelBlockingCall;
- { Return blocking call timeout error message }
- if Assigned( FOnErrorOccurred ) then
- FOnErrorOccurred( Self , WSAETIMEDOUT , 'Blocking call timed out' );
- end;
- end;
-
- { This is a wrapper method around the complexity of connecting a socket }
- procedure TCCSocket.CCSockConnect;
- var
- ReturnCode : Integer; { Generic return code var }
- TcpPChar : PChar; { Boilerplate TCP string }
- PortName : array[ 0 .. 31 ] of char; { PChar for port name }
- DataBuffer : array[ 0 .. 256 ] of char; { Generic buffer PChar }
- DummyValue : longint; { Must use variable call }
- begin
- { No port name set error }
- if FPort_Name = '' then
- begin
- SetSocketErrorData( 'No Valid Port Name in CCSockConnect');
- exit;
- end;
- { No IP address set error }
- if FIP_Address_Name = '' then
- begin
- SetSocketErrorData( 'No Valid IP Address in CCSockConnect');
- exit;
- end;
- { Set required family value }
- Socket_IP_Address.Socket_Family := AF_INET;
- { Move the port name into the PChar }
- StrPCopy( PortName , FPort_Name );
- { Set up the boilerplate pchar }
- TcpPChar := 'tcp';
- { Do blocking call on server }
- Socket_Server_Entry := getservbyname( PortName , TcpPChar );
- { If no reply then use default from name }
- if Socket_Server_Entry = nil then
- begin
- Socket_IP_Address.Socket_Port := htons( StrToInt( StrPas( PortName )));
- end
- else
- begin
- { Otherwise use the replied value }
- Socket_IP_Address.Socket_Port := Socket_Server_Entry^.Server_Port;
- end;
- { Move the IP address into the data buffer }
- StrPCopy( DataBuffer , FIP_Address_Name );
- { Turn it into a real IP address in binary form }
- Socket_IP_Address.Socket_Address.Full_Internet_Address :=
- inet_addr( DataBuffer );
- { If not found then do remote lookup }
- if Socket_IP_Address.Socket_Address.Full_Internet_Address = INADDR_NONE then
- begin
- { Call blocking function on IP name }
- Socket_Host_Entry := gethostbyname( DataBuffer );
- { If still no good then error out and exit }
- if Socket_Host_Entry = nil then
- begin
- SetSocketErrorData( 'Cannot convert host address in CCSockConnect');
- exit;
- end;
- { Otherwise get the address }
- Socket_IP_Address.Socket_Address := Socket_Host_Entry^.Host_Address^^;
- end;
- { Do protocol acquisition via blocking call }
- Socket_Protocol_Entry := getprotobyname( TcpPChar );
- { Create a socket }
- FSocket := socket( PF_INET ,
- SOCK_STREAM ,
- Socket_Protocol_Entry^.Protocol_Id );
- { If error code then exit with value set }
- if FSocket < 0 then
- begin
- SetSocketErrorData('CCSockConnect (socket)');
- exit;
- end;
- { If asynchmode then setup for asynch calls }
- if not FBlockingMode then
- begin
- { Do ass call and allow all callback states; note this will }
- { send a message when connected. }
- ReturnCode := WSAASyncSelect( FSocket , Handle , WM_ASYNCSELECT ,
- FD_READ or FD_WRITE or FD_OOB or FD_CLOSE or FD_CONNECT );
- { If get error say so }
- if ReturnCode <> 0 then SetSocketErrorData( 'WSAAsyncSelect' );
- end
- else
- begin
- { Otherwise set blocking mode }
- DummyValue := 0;
- ioctlsocket( FSocket , FIONBIO , DummyValue );
- { Set up timeout on blocking call }
- ActivateNonAsynchTimeout;
- { Attempt blocking connect }
- ReturnCode := connect( FSocket ,
- Socket_IP_Address ,
- SizeOf( Socket_IP_Address ));
- { Deactivate timeout on blocking call }
- DeactivateNonAsynchTimeout;
- { If any other error than WouldBlock signal connection error }
- if ReturnCode <> 0 then
- begin
- ReturnCode := WSAGetLastError;
- if ReturnCode <> WSAEWOULDBLOCK then
- SetSocketErrorData( 'CCSockConnect' );
- end;
- end;
- end;
-
- { This is a method to set the socket to a listening mode (ie server) }
- procedure TCCSocket.CCSockListen;
- var
- ReturnCode : Integer;
- TcpPChar : PChar;
- PortName : array[0..31] of char;
- DummyValue : Longint;
- { szData: array[0..256] of char;}
- begin
- DummyValue := 0;
- { Invalid Port Name error }
- if FPort_Name = '' then
- begin
- SetSocketErrorData( 'No Port Specified in CCSockListen' );
- exit;
- end;
- { Set default AF_INET family }
- Socket_IP_Address.Socket_Family := AF_INET;
- { Set any IP Address }
- Socket_IP_Address.Socket_Address.Full_Internet_Address := INADDR_ANY;
- { Set default TCP string }
- TcpPChar := 'tcp';
- { Create PChar of port name }
- StrPCopy( PortName , FPort_Name );
- { Use blocking call to get server }
- Socket_Server_Entry := getservbyname( PortName , TcpPChar );
- { If no entry the use default number otherwise use returned one }
- if Socket_Server_Entry = nil then
- Socket_IP_Address.Socket_Port := htons( StrToInt( StrPas( PortName )))
- else Socket_IP_Address.Socket_Port := Socket_Server_Entry^.Server_Port;
- { Use blocking call to get protocol }
- Socket_Protocol_Entry := getprotobyname( TcpPChar );
- { Set up the server socket }
- FMasterSocket := socket( PF_INET ,
- SOCK_STREAM ,
- Socket_Protocol_Entry^.Protocol_Id );
- { If socket error return code and exit }
- if FMasterSocket < 0 then
- begin
- SetSocketErrorData( 'socket' );
- exit;
- end;
- { Bind the server socket }
- ReturnCode := bind( FMasterSocket ,
- Socket_IP_Address,
- SizeOf( Socket_IP_Address ));
- { If socket error then signal and exit }
- if ReturnCode <> 0 then
- begin
- SetSocketErrorData( 'Bind' );
- exit;
- end;
- { Do a listen call to set up waiting state }
- ReturnCode := listen( FMasterSocket , 5 );
- { If socket error then signal and exit }
- if ReturnCode <> 0 then
- begin
- SetSocketErrorData( 'Listen' );
- exit;
- end;
- { If not blocking do asynch call }
- if not FBlockingMode then
- begin
- { Set up asynch call }
- ReturnCode := WSAASyncSelect( FMasterSocket ,
- Handle ,
- WM_ASYNCSELECT ,
- FD_READ or FD_WRITE or FD_OOB
- or FD_ACCEPT or FD_CLOSE );
- { If error then signal }
- if ReturnCode <> 0 then SetSocketErrorData('WSAASyncSelect');
- end
- else ioctlsocket( FMasterSocket , FIONBIO , DummyValue ); { otherwise set blocking }
- end;
-
- { This method terminates a listening mode (server) }
- procedure TCCSocket.CCSockCancelListen;
- var
- ReturnCode : Integer; { status code var }
- begin
- { if not blocking then turn off asynch mode }
- if not FBlockingMode then
- WSAASyncSelect( FMasterSocket , Handle , WM_ASYNCSELECT , 0 );
- { Shutdown call }
- shutdown( FMasterSocket , 2 );
- { Close the socket }
- ReturnCode := closesocket( FMasterSocket );
- { If socket error signal it }
- if ReturnCode <> 0 then
- SetSocketErrorData( 'CancelListen (closesocket)' );
- { kill socket id }
- FMasterSocket := 0;
- end;
-
- { This is the blocking mode accept procedure }
- function TCCSocket.CCSockAccept: TSocket;
- var
- TheDataLength : Integer; { data length }
- DummyValue : Longint;
- begin
- Dummyvalue := 0;
- { Get length of the address variable }
- TheDataLength := sizeof( Socket_IP_Address );
- { if blocking then do timeout }
- if FBlockingMode then ActivateNonAsynchTimeout;
- { Do blocking accept call }
- FSocket := accept( FMasterSocket ,
- Socket_IP_Address ,
- TheDataLength );
- { If blocking }
- if FBlockingMode then
- begin
- { Kill timeout timer }
- DeactivateNonAsynchTimeout;
- { Turn on blocking on accepted socket }
- ioctlsocket( FSocket , FIONBIO , DummyValue );
- end;
- { If no accept then signal error }
- if FSocket < 0 then SetSocketErrorData( 'Accept' );
- { Return Socket ID }
- Result := FSocket;
- end;
-
- { Close a socket in either mode }
- procedure TCCSocket.CCSockClose;
- var
- ReturnCode : Integer; { status code var }
- LingerRecord : Lingering_Control; { linger var }
- LingerArray : array[ 0 .. 3 ] of char absolute LingerRecord;
- { pointer into la }
- begin
- { If not blocking then turn of asynch messaging }
- if not FBlockingMode then
- WSAASyncSelect( FSocket , Handle , WM_ASYNCSELECT , 0 );
- { cancel any blocking }
- if WSAIsBlocking then WSACancelBlockingCall;
- { shut down the socket }
- shutdown( FSocket , 2 );
- { Set up the linger record }
- LingerRecord.Linger_Status := 1;
- LingerRecord.Linger_Interval := 0;
- { Set up the linger status via setsockopt }
- setsockopt( FSocket ,
- SOL_SOCKET ,
- SO_LINGER ,
- LingerArray ,
- sizeof( LingerRecord ));
- { Do the close call }
- ReturnCode := closesocket( FSocket );
- { signal error if one happens }
- if ReturnCode <> 0 then SetSocketErrorData( 'Disconnect (closesocket)' );
- { set socket to invalid value }
- FSocket := INVALID_SOCKET;
- end;
-
- { This sets up internal values for retrieval in case errors occur }
- procedure TCCSocket.SetSocketErrorData( SocketFunction : string );
- begin
- { Get any winsock error }
- ErrorCode := WSAGetLastError;
- { Get text description of error }
- WinsockErrorMessage := GetSocketErrorDescription( ErrorCode );
- { Setup full error message for user friendliness }
- if WinsockErrorMessage <> 'No Error' then
- FullErrorMessage := 'Error '+ WinsockErrorMessage +
- ' in function ' + SocketFunction else FullErrorMessage :=
- SocketFunction;
- { call error event handler }
- if Assigned( FOnErrorOccurred ) then
- FOnErrorOccurred( Self , ErrorCode , FullErrorMessage );
- end;
-
- { Boilerplate error descriptions }
- function TCCSocket.GetSocketErrorDescription( ErrorCode : Integer ) : string;
- begin
- case ErrorCode of
- WSAEINTR:
- GetSocketErrorDescription := 'System Interrupt Failure';
- WSAEBADF:
- GetSocketErrorDescription := 'Bad File Failure';
- WSAEACCES:
- GetSocketErrorDescription := 'File Permission Denied Failure';
- WSAEFAULT:
- GetSocketErrorDescription := 'Bad IP Address Failure';
- WSAEINVAL:
- GetSocketErrorDescription := 'Invalid Winsock API Call Argument Failure';
- WSAEMFILE:
- GetSocketErrorDescription := 'Too Many Open Files Failure';
- WSAEWOULDBLOCK:
- GetSocketErrorDescription := 'Operation Would Block Failure';
- WSAEINPROGRESS:
- GetSocketErrorDescription := 'Operation Blocking Failure';
- WSAEALREADY:
- GetSocketErrorDescription := 'Operation Already in Progress Failure';
- WSAENOTSOCK:
- GetSocketErrorDescription := 'Invalid Socket Operation Failure';
- WSAEDESTADDRREQ:
- GetSocketErrorDescription := 'No Destination Address Failure';
- WSAEMSGSIZE:
- GetSocketErrorDescription := 'Invalid Message Length Failure';
- WSAEPROTOTYPE:
- GetSocketErrorDescription := 'Invalid Protocol For Socket Failure';
- WSAENOPROTOOPT:
- GetSocketErrorDescription := 'Unavilable Protocol Failure';
- WSAEPROTONOSUPPORT:
- GetSocketErrorDescription := 'Unsupported Protocol Failure';
- WSAESOCKTNOSUPPORT:
- GetSocketErrorDescription := 'Unsupported Socket Type Failure';
- WSAEOPNOTSUPP:
- GetSocketErrorDescription := 'Unsupported Socket Operation Failure';
- WSAEPFNOSUPPORT:
- GetSocketErrorDescription := 'Unsupported Protocol Family Failure';
- WSAEAFNOSUPPORT:
- GetSocketErrorDescription := 'Invalid Protocol-Address Family Failure';
- WSAEADDRINUSE:
- GetSocketErrorDescription := 'Address In Use Failure';
- WSAEADDRNOTAVAIL:
- GetSocketErrorDescription := 'Unavailable Address Failure';
- WSAENETDOWN:
- GetSocketErrorDescription := 'Network Down Failure';
- WSAENETUNREACH:
- GetSocketErrorDescription := 'Network Unreachable Failure';
- WSAENETRESET:
- GetSocketErrorDescription := 'Network Connection Dropped Failure';
- WSAECONNABORTED:
- GetSocketErrorDescription := 'Software Abort Failure';
- WSAECONNRESET:
- GetSocketErrorDescription := 'Peer Connection Reset Failure';
- WSAENOBUFS:
- GetSocketErrorDescription := 'Buffer Overflow Failure';
- WSAEISCONN:
- GetSocketErrorDescription := 'Connected Socket Failure';
- WSAENOTCONN:
- GetSocketErrorDescription := 'Unconnected Socket Failure';
- WSAESHUTDOWN:
- GetSocketErrorDescription := 'Closed Socket Send Failure';
- WSAETOOMANYREFS:
- GetSocketErrorDescription := 'Reference Count Overflow Failure';
- WSAETIMEDOUT:
- GetSocketErrorDescription := 'Connection Timeout Failure';
- WSAECONNREFUSED:
- GetSocketErrorDescription := 'Connection Refusal Failure';
- WSAELOOP:
- GetSocketErrorDescription := 'Symbolic Link Overflow Failure';
- WSAENAMETOOLONG:
- GetSocketErrorDescription := 'Invalid File Name Failure';
- WSAEHOSTDOWN:
- GetSocketErrorDescription := 'Host Down Failure';
- WSAEHOSTUNREACH:
- GetSocketErrorDescription := 'Host Unreachable Failure';
- WSAENOTEMPTY:
- GetSocketErrorDescription := 'Non-Empty Directory Removal Failure';
- WSAEPROCLIM:
- GetSocketErrorDescription := 'Process Overflow Failure';
- WSAEUSERS:
- GetSocketErrorDescription := 'Users Overflow Failure';
- WSAEDQUOT:
- GetSocketErrorDescription := 'Disk Quota Overflow Failure';
- WSAESTALE:
- GetSocketErrorDescription := 'Invalid File Handle Failure';
- WSAEREMOTE:
- GetSocketErrorDescription := 'File Path Overflow Failure';
- WSASYSNOTREADY:
- GetSocketErrorDescription := 'Unavailable Sub-Network Failure';
- WSAVERNOTSUPPORTED:
- GetSocketErrorDescription := 'Winsock Application Compatibility Failure';
- WSANOTINITIALISED:
- GetSocketErrorDescription := 'WinSock Uninitialized Failure';
- WSAHOST_NOT_FOUND:
- GetSocketErrorDescription := 'Host Not Located Failure';
- WSATRY_AGAIN:
- GetSocketErrorDescription := 'Non-Authority Host Not Located Failure';
- WSANO_RECOVERY:
- GetSocketErrorDescription := 'Fatal Winsock Error Failure';
- WSANO_DATA:
- GetSocketErrorDescription := 'Data Not Available Failure';
- else GetSocketErrorDescription := 'No Error';
- end;
- end;
-
- { Activate timeout procedure }
- procedure TCCSocket.ActivateNonAsynchTimeout;
- begin
- if FTimeoutValue > 0 then
- SetTimer( Handle , 10 , FTimeoutValue * 1000 , nil );
- end;
-
- { Deactivate timeout procedure }
- procedure TCCSocket.DeactivateNonAsynchTimeout;
- begin
- if FTimeoutValue > 0 then KillTimer( Handle , 10 );
- end;
-
- end.